package room

import (
	"errors"
	"server/common"

	"github.com/mitchellh/mapstructure"
	"github.com/sirupsen/logrus"
)

// -------------------------------------------------------------------------------------------------
//
// -------------------------------------------------------------------------------------------------
func (s *RoomService) checkConnectTransportReqData(data common.SFUConnectTransportReqData) error {
	// Check if transport ID is provided
	if data.TransportId == "" {
		return errors.New("transport ID is required in connect transport request")
	}

	// Check if DTLS parameters are provided
	if data.DtlsParameters == nil {
		return errors.New("DTLS parameters are required in connect transport request")
	}

	// Check send/receive mode
	if data.SendOrRecv != common.SEND && data.SendOrRecv != common.RECV {
		return errors.New("send/recv mode must be either 'send' or 'recv'")
	}

	// Check if room ID is provided
	if data.RoomId == "" {
		return errors.New("room ID is required in connect transport request")
	}

	// Check if user ID is provided
	if data.UserId == "" {
		return errors.New("user ID is required in connect transport request")
	}

	// Check if room exists
	if !s.roomMgr.RoomExists(data.RoomId) {
		return errors.New("room does not exist")
	}

	if data.SendOrRecv == common.SEND {
		if !s.roomMgr.MatchSendTransport(data.RoomId, data.UserId, data.TransportId) {
			return errors.New("transport ID does not match send transport for the user in the room")
		}
	} else {
		if !s.roomMgr.MatchRecvTransport(data.RoomId, data.UserId, data.TransportId) {
			return errors.New("transport ID does not match send transport for the user in the room")
		}
	}

	return nil
}

// -------------------------------------------------------------------------------------------------
//
// -------------------------------------------------------------------------------------------------
func (s *RoomService) sendConnectTransportResponse(rid string, code int, msg string, connId string,
	data common.SFUConnectTransportReqData) {
	resMsg := common.Message{
		Cmd: common.SFU_CONNECT_TRANSPORT_RES,
		Rid: rid,
		Data: common.ResMsgData{
			Code: code,
			Msg:  msg,
			Data: common.SFUConnectTransportResData{
				RoomId:      data.RoomId,
				UserId:      data.UserId,
				TransportId: data.TransportId,
			},
		},
	}
	s.dispatcher.Dispatch(resMsg, s.serviceInfo, common.AccessServiceInfo, connId)
}

// -------------------------------------------------------------------------------------------------
//
// -------------------------------------------------------------------------------------------------
func (s *RoomService) handleConnectTransportReq(msg common.Message, from common.ServiceInfo,
	connId string) error {
	LOG().WithFields(logrus.Fields{
		"msg":    common.ToJson(msg),
		"from":   from,
		"connId": connId,
	}).Info("Handling SFU Connect Transport Request")

	var reqData common.SFUConnectTransportReqData
	if err := mapstructure.Decode(msg.Data, &reqData); err != nil {
		LOG(msg.Rid).WithError(err).Error("failed to decode connect transport request data")
		return err
	}

	if err := s.checkConnectTransportReqData(reqData); err != nil {
		LOG(msg.Rid).WithError(err).Error("invalid connect transport request data")
		s.sendConnectTransportResponse(msg.Rid, 1, err.Error(), connId, reqData)
		return nil
	}

	if err := s.roomMgr.ConnectTransport(msg.Rid, reqData); err != nil {
		LOG(msg.Rid).WithError(err).Error("failed to connect transport")
		s.sendConnectTransportResponse(msg.Rid, 1, err.Error(), connId, reqData)
		return nil
	}

	s.sendConnectTransportResponse(msg.Rid, 0, "success", connId, reqData)

	return nil
}
